package org.zoomdev.zoom.dao.impl;

import org.zoomdev.zoom.common.caster.Caster;
import org.zoomdev.zoom.common.caster.ValueCaster;
import org.zoomdev.zoom.dao.Record;
import org.zoomdev.zoom.dao.alias.NameAdapter;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

final class RecordUtils {

    private static final ValueCaster blobCaster;
    private static final ValueCaster clobCaster;

    static {

        blobCaster = Caster.wrap(Blob.class, byte[].class);
        clobCaster = Caster.wrap(Clob.class, String.class);

    }

    static final List<Record> build(ResultSet rs, NameAdapter policy) throws SQLException {
        List<Record> result = new ArrayList<Record>();
        ResultSetMetaData rsmd = rs.getMetaData();
        int columnCount = rsmd.getColumnCount();
        String[] labelNames = new String[columnCount + 1];
        int[] types = new int[columnCount + 1];
        buildLabelNamesAndTypes(rsmd, labelNames, types, policy);
        while (rs.next()) {
            result.add(build(columnCount, rs, types, labelNames));
        }
        return result;
    }

    static final void buildLabelNamesAndTypes(ResultSetMetaData rsmd, String[] labelNames, int[] types, NameAdapter policy) throws SQLException {
        for (int i = 1; i < labelNames.length; i++) {
            labelNames[i] = policy.getFieldName(rsmd.getColumnLabel(i));
            types[i] = rsmd.getColumnType(i);
        }
    }

    static final Record build(int columnCount, ResultSet rs, int[] types, String[] labelNames) throws SQLException {
        Record map = new Record();
        for (int i = 1; i <= columnCount; i++) {
            map.put(labelNames[i], getValue(types[i], rs, i));
        }
        return map;
    }

    static final Object getValue(int type, ResultSet rs, int i) throws SQLException {
        if (type < Types.BLOB)
            return rs.getObject(i);
        else if (type == Types.CLOB)
            return clobCaster.to(rs.getClob(i));
        else if (type == Types.NCLOB)
            return clobCaster.to(rs.getNClob(i));
        else if (type == Types.BLOB)
            return blobCaster.to(rs.getBlob(i));
        else
            return rs.getObject(i);
    }

    static final Record buildOne(ResultSet rs, NameAdapter policy) throws SQLException {
        ResultSetMetaData rsmd = rs.getMetaData();
        int columnCount = rsmd.getColumnCount();
        Record map = new Record();
        for (int i = 1; i <= columnCount; i++) {
            int type = rsmd.getColumnType(i);
            String name = rsmd.getColumnName(i);
            map.put(policy.getFieldName(name), getValue(type, rs, i));
        }

        return map;
    }


}
